home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / nslookup / getinfo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-11-27  |  18.4 KB  |  763 lines

  1. /*
  2.  * Copyright (c) 1985 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #ifndef lint
  19. static char sccsid[] = "@(#)getinfo.c    5.18 (Berkeley) 6/18/88";
  20. #endif /* not lint */
  21.  
  22. /*
  23.  *******************************************************************************
  24.  *
  25.  *  getinfo.c --
  26.  *
  27.  *    Routines to create requests to name servers 
  28.  *    and interpret the answers.
  29.  *
  30.  *    Adapted from 4.3BSD BIND gethostnamadr.c
  31.  *
  32.  *******************************************************************************
  33.  */
  34.  
  35. #include <sys/types.h>
  36. #include <sys/socket.h>
  37. #include <netinet/in.h>
  38. #include <stdio.h>
  39. #include <ctype.h>
  40. #include <arpa/nameser.h>
  41. #include <resolv.h>
  42. #include "res.h"
  43.  
  44. extern char *_res_resultcodes[];
  45. extern char *res_skip();
  46.  
  47. #define    MAXALIASES    35
  48. #define MAXADDRS    35
  49. #define MAXDOMAINS    35
  50. #define MAXSERVERS    10
  51.  
  52. static char *addr_list[MAXADDRS + 1];
  53.  
  54. static char *host_aliases[MAXALIASES];
  55. static int   host_aliases_len[MAXALIASES];
  56. static char  hostbuf[BUFSIZ+1];
  57.  
  58. typedef struct {
  59.     char *name;
  60.     char *domain[MAXDOMAINS];
  61.     int   numDomains;
  62.     char *address[MAXADDRS];
  63.     int   numAddresses;
  64. } ServerTable;
  65.  
  66. ServerTable server[MAXSERVERS];
  67.  
  68. typedef union {
  69.     HEADER qb1;
  70.     char qb2[PACKETSZ];
  71. } querybuf;
  72.  
  73. typedef union {
  74.     long al;
  75.     char ac;
  76. } align;
  77.  
  78. #define GetShort(cp)    _getshort(cp); cp += sizeof(unsigned short);
  79.  
  80.  
  81. /*
  82.  *******************************************************************************
  83.  *
  84.  *  GetAnswer --
  85.  *
  86.  *    Interprets an answer packet and retrieves the following
  87.  *    information:
  88.  *
  89.  *  Results:
  90.  *      SUCCESS         the info was retrieved.
  91.  *      NO_INFO         the packet did not contain an answer.
  92.  *    NONAUTH        non-authoritative information was found.
  93.  *      ERROR           the answer was malformed.
  94.  *      Other errors    returned in the packet header.
  95.  *
  96.  *******************************************************************************
  97.  */
  98.  
  99. static int
  100. GetAnswer(nsAddrPtr, queryType, msg, msglen, iquery, hostPtr, isserver)
  101.     struct in_addr     *nsAddrPtr;
  102.     char         *msg;
  103.     int         queryType;
  104.     int         msglen;
  105.     Boolean         iquery;
  106.     register HostInfo    *hostPtr;
  107.     Boolean        isserver;
  108. {
  109.     register HEADER     *headerPtr;
  110.     register char     *cp;
  111.     querybuf         answer;
  112.     char         *eom, *bp, **aliasPtr;
  113.     char         **addrPtr;
  114.     char        *namePtr;
  115.     char        *dnamePtr;
  116.     int         type, class;
  117.     int         qdcount, ancount, arcount, nscount, buflen;
  118.     int         origClass;
  119.     int         numAliases = 0;
  120.     int         numAddresses = 0;
  121.     int         n, i, j;
  122.     int         len;
  123.     int         dlen;
  124.     int         status;
  125.     int            numServers;
  126.     Boolean         haveanswer;
  127.  
  128.  
  129.     /*
  130.      *  If the hostPtr was used before, free up the calloc'd areas.
  131.      */
  132.     FreeHostInfoPtr(hostPtr);
  133.     
  134.     status = SendRequest(nsAddrPtr, msg, msglen, (char *) &answer, 
  135.                 sizeof(answer), &n);
  136.  
  137.     if (status != SUCCESS) {
  138.         if (_res.options & RES_DEBUG2)
  139.             printf("SendRequest failed\n");
  140.         return (status);
  141.     }
  142.     eom = (char *) &answer + n;
  143.  
  144.     headerPtr = (HEADER *) &answer;
  145.     qdcount = ntohs(headerPtr->qdcount);
  146.     ancount = ntohs(headerPtr->ancount);
  147.     arcount = ntohs(headerPtr->arcount);
  148.     nscount = ntohs(headerPtr->nscount);
  149.  
  150.     if (headerPtr->rcode != NOERROR) {
  151.     if (_res.options & RES_DEBUG && !isserver) {
  152.         printf("Failed: %s, num. answers = %d, ns = %d, additional = %d\n", 
  153.             _res_resultcodes[headerPtr->rcode], ancount, nscount,
  154.             arcount);
  155.     }
  156.     return (headerPtr->rcode);
  157.     }
  158.  
  159.     /*
  160.      * If there are no answer, n.s. or additional records 
  161.      * then return with an error.
  162.      */
  163.     if (ancount == 0 && nscount == 0 && arcount == 0) {
  164.     return (NO_INFO);
  165.     }
  166.  
  167.  
  168.     bp        = hostbuf;
  169.     buflen = sizeof(hostbuf);
  170.     cp        = (char *) &answer + sizeof(HEADER);
  171.  
  172.     /*
  173.      * For inverse queries, the desired information is returned
  174.      * in the question section. If there are no question records,
  175.      * return with an error.
  176.      *
  177.      */
  178.     if (qdcount != 0) {
  179.     if (iquery) {
  180.         if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0) {
  181.         return (ERROR);
  182.         }
  183.         cp += n + QFIXEDSZ;
  184.         len = strlen(bp) + 1;
  185.         hostPtr->name = Calloc(1, len);
  186.         bcopy(bp, hostPtr->name, len);
  187.     } else {
  188.         cp += dn_skipname(cp, eom) + QFIXEDSZ;
  189.     }
  190.     while (--qdcount > 0) {
  191.         cp += dn_skipname(cp, eom) + QFIXEDSZ;
  192.     }
  193.     } else if (iquery) {
  194.     return (NO_INFO);
  195.     }
  196.  
  197.     aliasPtr     = host_aliases;
  198.     addrPtr    = addr_list;
  199.     haveanswer     = FALSE;
  200.  
  201.     /*
  202.      * Scan through the answer resource records.
  203.      * Answers for address query types are saved.
  204.      * Other query type answers are just printed.
  205.      */
  206.     if (!isserver && !headerPtr->aa && headerPtr->ancount != 0) {
  207.     printf("Non-authoritative answer:\n");
  208.     }
  209.     while (--ancount >= 0 && cp < eom) {
  210.     if (queryType != T_A) {
  211.         if ((cp = Print_rr(cp, (char *) &answer, eom, stdout)) == NULL) {
  212.         return(ERROR);
  213.         }
  214.         continue;
  215.     } else {
  216.         if ((n = dn_expand((char *) &answer, eom, cp, bp, buflen)) < 0) {
  217.         return(ERROR);
  218.         }
  219.         cp   += n;
  220.         type  = GetShort(cp);
  221.         class = GetShort(cp);
  222.         cp   += sizeof(u_long);     /* skip TTL */
  223.         dlen  = GetShort(cp);
  224.         if (type == T_CNAME) {
  225.         /*
  226.          * Found an alias.
  227.          */
  228.         cp += dlen;
  229.         if (aliasPtr >= &host_aliases[MAXALIASES-1]) {
  230.             continue;
  231.         }
  232.         *aliasPtr++ = bp;
  233.         n = strlen(bp) + 1;
  234.         host_aliases_len[numAliases] = n;
  235.         numAliases++;
  236.         bp += n;
  237.         buflen -= n;
  238.         continue;
  239.         } else if (type == T_PTR) {
  240.         /*
  241.          *  Found a "pointer" to the real name.
  242.          */
  243.         if((n= dn_expand((char *)&answer, eom, cp, bp,buflen)) < 0) {
  244.             cp += n;
  245.             continue;
  246.         }
  247.         cp += n;
  248.         len = strlen(bp) + 1;
  249.         hostPtr->name = Calloc(1, len);
  250.         bcopy(bp, hostPtr->name, len);
  251.         haveanswer = TRUE;
  252.         break;
  253.         } else if (type != T_A) {
  254.         cp += dlen;
  255.         continue;
  256.         }
  257.         if (haveanswer) {
  258.         /*
  259.          * If we've already got 1 address, we aren't interested
  260.          * in addresses with a different length or class.
  261.          */
  262.         if (dlen != hostPtr->addrLen) {
  263.             cp += dlen;
  264.             continue;
  265.         }
  266.         if (class != origClass) {
  267.             cp += dlen;
  268.             continue;
  269.         }
  270.         } else {
  271.         /*
  272.          * First address: record its length and class so we
  273.          * only save additonal ones with the same attributes.
  274.          */
  275.         hostPtr->addrLen = dlen;
  276.         origClass = class;
  277.         hostPtr->addrType = (class == C_IN) ? AF_INET : AF_UNSPEC;
  278.         if (!iquery) {
  279.             len = strlen(bp) + 1;
  280.             hostPtr->name = Calloc(1, len);
  281.             bcopy(bp, hostPtr->name, len);
  282.         }
  283.         }
  284.         bp += (((u_long)bp) % sizeof(align));
  285.  
  286.         if (bp + dlen >= &hostbuf[sizeof(hostbuf)]) {
  287.         if (_res.options & RES_DEBUG) {
  288.             printf("Size (%d) too big\n", dlen);
  289.         }
  290.         break;
  291.         }
  292.         bcopy(cp, *addrPtr++ = bp, dlen);
  293.         bp +=dlen;
  294.         cp += dlen;
  295.         numAddresses++;
  296.         haveanswer = TRUE; 
  297.     }
  298.     }
  299.  
  300.     if (queryType == T_A && haveanswer) {
  301.  
  302.     /*
  303.      *  Go through the alias and address lists and return them
  304.      *  in the hostPtr variable.
  305.      */
  306.  
  307.     if (numAliases > 0) {
  308.         hostPtr->aliases = (char **) Calloc(1 + numAliases, sizeof(char *));
  309.         for (i = 0; i < numAliases; i++) {
  310.         hostPtr->aliases[i] = Calloc(1, host_aliases_len[i]);
  311.         bcopy(host_aliases[i], hostPtr->aliases[i],host_aliases_len[i]);
  312.         }
  313.         hostPtr->aliases[i] = NULL;
  314.     }
  315.     if (numAddresses > 0) {
  316.         hostPtr->addrList = (char **)Calloc(1+numAddresses, sizeof(char *));
  317.         for (i = 0; i < numAddresses; i++) {
  318.         hostPtr->addrList[i] = Calloc(1, hostPtr->addrLen);
  319.         bcopy(addr_list[i], hostPtr->addrList[i], hostPtr->addrLen);
  320.         }
  321.         hostPtr->addrList[i] = NULL;
  322.     }
  323. #ifdef verbose
  324.     if (headerPtr->aa || nscount == 0) {
  325.         hostPtr->servers = NULL;
  326.         return (SUCCESS);
  327.     }
  328. #else
  329.     hostPtr->servers = NULL;
  330.     return (SUCCESS);
  331. #endif
  332.     }
  333.  
  334.     /*
  335.      * At this point, for the T_A query type, only empty answers remain.
  336.      * For other query types, additional information might be found
  337.      * in the additional resource records part.
  338.      */
  339.  
  340.     cp = res_skip((char *) &answer, 2, eom);
  341.  
  342.     numServers = 0;
  343.     while (--nscount >= 0 && cp < eom) {
  344.     /*
  345.      *  Go through the NS records and retrieve the names of hosts 
  346.      *  that serve the requested domain.
  347.      */
  348.  
  349.     if ((n = dn_expand((char *) &answer, eom, cp, bp, buflen)) < 0) {
  350.         return(ERROR);
  351.     }
  352.     cp += n;
  353.     len = strlen(bp) + 1;
  354.     dnamePtr = Calloc(1, len);   /* domain name */
  355.     bcopy(bp, dnamePtr, len);
  356.  
  357.     type  = GetShort(cp);
  358.     class = GetShort(cp);
  359.     cp   += sizeof(u_long);     /* skip TTL */
  360.     dlen  = GetShort(cp);
  361.  
  362.     if (type != T_NS) {
  363.         cp += dlen;
  364.     } else {
  365.         Boolean    found;
  366.  
  367.         if ((n = dn_expand((char *) &answer, eom, cp, bp, buflen)) < 0) {
  368.         return(ERROR);
  369.         }
  370.         cp += n;
  371.         len = strlen(bp) + 1;
  372.         namePtr = Calloc(1, len); /* server host name */
  373.         bcopy(bp, namePtr, len);
  374.  
  375.         /*
  376.         * Store the information keyed by the server host name.
  377.         */
  378.         found = FALSE;
  379.         for (j = 0; j < numServers; j++) {
  380.         if (strcmp(namePtr, server[j].name) == 0) {
  381.             found = TRUE;
  382.             free(namePtr);
  383.             break;
  384.         }
  385.         }
  386.         if (found) {
  387.         server[j].numDomains++;
  388.         if (server[j].numDomains <= MAXDOMAINS) {
  389.             server[j].domain[server[j].numDomains-1] = dnamePtr;
  390.         }
  391.         } else {
  392.         if (numServers >= MAXSERVERS) {
  393.             break;
  394.         }
  395.         server[numServers].name = namePtr;
  396.         server[numServers].domain[0] = dnamePtr;
  397.         server[numServers].numDomains = 1;
  398.         server[numServers].numAddresses = 0;
  399.         numServers++;
  400.         }
  401.     }
  402.     }
  403.  
  404.     if (!headerPtr->aa && (queryType != T_A) && arcount > 0) {
  405.     printf("Authoritative answers can be found from:\n");
  406.     }
  407.  
  408.     /*
  409.      * Additional resource records contain addresses of servers.
  410.      */
  411.     cp = res_skip((char *) &answer, 3, eom);
  412.     while (--arcount >= 0 && cp < eom) {
  413.     /*
  414.      * If we don't need to save the record, just print it.
  415.      */
  416.     if (queryType != T_A) {
  417.         if ((cp = Print_rr(cp, (char *) &answer, eom, stdout)) == NULL) {
  418.         return(ERROR);
  419.         }
  420.         continue;
  421.  
  422.     } else {
  423.       if ((n = dn_expand((char *) &answer, eom, cp, bp, buflen)) < 0) {
  424.           break;
  425.       }
  426.       cp   += n;
  427.       type  = GetShort(cp);
  428.       class = GetShort(cp);
  429.       cp   += sizeof(u_long);     /* skip TTL */
  430.       dlen  = GetShort(cp);
  431.  
  432.       if (type != T_A)  {
  433.           cp += dlen;
  434.           continue;
  435.       } else {
  436.           for (j = 0; j < numServers; j++) {
  437.             if (strcmp(bp, server[j].name) == 0) {
  438.           server[j].numAddresses++;
  439.           if (server[j].numAddresses <= MAXADDRS) {
  440.            server[j].address[server[j].numAddresses-1] = Calloc(1,dlen);
  441.            bcopy(cp,server[j].address[server[j].numAddresses-1],dlen);
  442.            break;
  443.           }
  444.             }
  445.           }
  446.           cp += dlen;
  447.       }
  448.       }
  449.     }
  450.  
  451.     /*
  452.      * If we are returning name server info, transfer it to the hostPtr.
  453.      */
  454.     if (numServers > 0) {
  455.     hostPtr->servers = (ServerInfo **) 
  456.                     Calloc(numServers+1, sizeof(ServerInfo *));
  457.  
  458.     for (i = 0; i < numServers; i++) {
  459.         hostPtr->servers[i] = (ServerInfo *) Calloc(1, sizeof(ServerInfo));
  460.         hostPtr->servers[i]->name = server[i].name;
  461.  
  462.  
  463.         hostPtr->servers[i]->domains = (char **)
  464.                     Calloc(server[i].numDomains+1,sizeof(char *));
  465.         for (j = 0; j < server[i].numDomains; j++) {
  466.         hostPtr->servers[i]->domains[j] = server[i].domain[j];
  467.         }
  468.         hostPtr->servers[i]->domains[j] = NULL;
  469.  
  470.  
  471.         hostPtr->servers[i]->addrList = (char **)
  472.                   Calloc(server[i].numAddresses+1,sizeof(char *));
  473.         for (j = 0; j < server[i].numAddresses; j++) {
  474.         hostPtr->servers[i]->addrList[j] = server[i].address[j];
  475.         }
  476.         hostPtr->servers[i]->addrList[j] = NULL;
  477.  
  478.     }
  479.     hostPtr->servers[i] = NULL;
  480.     }
  481.  
  482.  
  483.     if (queryType != T_A) {
  484.     return(SUCCESS);
  485.     } else {
  486.     return(NONAUTH);
  487.     }
  488. }
  489.  
  490. /*
  491. *******************************************************************************
  492. *
  493. *  GetHostInfo --
  494. *
  495. *    Retrieves host name, address and alias information
  496. *    for a domain.
  497. *
  498. *  Results:
  499. *    ERROR        - res_mkquery failed.
  500. *    + return values from GetAnswer()
  501. *
  502. *******************************************************************************
  503. */
  504.  
  505. int
  506. GetHostInfo(nsAddrPtr, queryClass, queryType, name, hostPtr, isserver)
  507.     struct in_addr    *nsAddrPtr;
  508.     int         queryClass;
  509.     int         queryType;
  510.     char         *name;
  511.     HostInfo         *hostPtr;
  512.     Boolean        isserver;
  513. {
  514.     int          n;
  515.     int          result;
  516.     register char    *cp, **domain;
  517.     extern char        *hostalias();
  518.  
  519.     /* catch explicit addresses */
  520.     if (isdigit(*name) && (queryType == T_A)) {
  521.     long ina;
  522.  
  523.     ina = inet_addr(name);
  524.  
  525.     if (ina == -1)
  526.         return(ERROR);
  527.  
  528.     hostPtr->name = Calloc(strlen(name)+3, 1);
  529.     (void)sprintf(hostPtr->name,"[%s]",name);
  530.     hostPtr->aliases = NULL;
  531.     hostPtr->servers = NULL;
  532.     hostPtr->addrType = AF_INET;
  533.     hostPtr->addrLen = 4;
  534.     hostPtr->addrList = (char **)Calloc(2, sizeof(char *));
  535.     hostPtr->addrList[0] = Calloc(sizeof(long), sizeof(char));
  536.     bcopy((char *)&ina,hostPtr->addrList[0],sizeof(ina));
  537.     hostPtr->addrList[1] = 0;
  538.  
  539.     return(SUCCESS);
  540.     }
  541.  
  542.     for (cp = name, n = 0; *cp; cp++)
  543.         if (*cp == '.')
  544.             n++;
  545.     if ((n && *--cp == '.') ||
  546.     (isserver == 0 && (_res.options & RES_DEFNAMES) == 0)) {
  547.         int defflag = _res.options & RES_DEFNAMES;
  548.  
  549.         _res.options &= ~RES_DEFNAMES;
  550.         if (n && *cp == '.')
  551.             *cp = 0;
  552.         result = GetHostDomain(nsAddrPtr, queryClass, queryType,
  553.             name, (char *)NULL, hostPtr, isserver);
  554.         if (n && *cp == 0)
  555.             *cp = '.';
  556.         if (defflag)
  557.             _res.options |= RES_DEFNAMES;
  558.         return (result);
  559.     }
  560.     if (n == 0 && (cp = hostalias(name)))
  561.         return (GetHostDomain(nsAddrPtr, queryClass, queryType,
  562.             cp, (char *)NULL, hostPtr, isserver));
  563.     for (domain = _res.dnsrch; *domain; domain++) {
  564.         result = GetHostDomain(nsAddrPtr, queryClass, queryType,
  565.             name, *domain, hostPtr, isserver);
  566.         if ((result != NXDOMAIN && result != NO_INFO) ||
  567.         (_res.options & RES_DNSRCH) == 0)
  568.             return (result);
  569.     }
  570.     if (n)
  571.         return (GetHostDomain(nsAddrPtr, queryClass, queryType,
  572.             name, (char *)NULL, hostPtr, isserver));
  573.     return (result);
  574. }
  575.  
  576. GetHostDomain(nsAddrPtr, queryClass, queryType, name, domain, hostPtr, isserver)
  577.     struct in_addr    *nsAddrPtr;
  578.     int         queryClass;
  579.     int         queryType;
  580.     char         *name, *domain;
  581.     HostInfo        *hostPtr;
  582.     Boolean        isserver;
  583. {
  584.     querybuf buf;
  585.     char nbuf[2*MAXDNAME+2];
  586.     int n;
  587.  
  588.     if (domain) {
  589.         (void)sprintf(nbuf, "%.*s.%.*s",
  590.             MAXDNAME, name, MAXDNAME, domain);
  591.         name = nbuf;
  592.     }
  593.     n = res_mkquery(QUERY, name, queryClass, queryType,
  594.             (char *)0, 0, (char *)0, (char *) &buf, sizeof(buf));
  595.     if (n < 0) {
  596.     if (_res.options & RES_DEBUG) {
  597.         printf("Res_mkquery failed\n");
  598.     }
  599.     return (ERROR);
  600.     }
  601.  
  602.     n = GetAnswer(nsAddrPtr, queryType, (char *) &buf, n, 0, hostPtr,
  603.     isserver);
  604.  
  605.     /*
  606.      * GetAnswer didn't find a name, so set it to the specified one.
  607.      */
  608.     if (n == NONAUTH) {
  609.     if (hostPtr->name == NULL) {
  610.         int len = strlen(name) + 1;
  611.         hostPtr->name = Calloc(len, sizeof(char));
  612.         bcopy(name, hostPtr->name, len);
  613.     }
  614.     }
  615.     return(n);
  616. }
  617.  
  618.  
  619. /*
  620. *******************************************************************************
  621. *
  622. *  FindHostInfo --
  623. *
  624. *    Performs an inverse query to find the host name
  625. *    that corresponds to the given address.
  626. *
  627. *  Results:
  628. *    ERROR        - res_mkquery failed.
  629. *    + return values from GetAnswer()
  630. *
  631. *******************************************************************************
  632. */
  633.  
  634. int
  635. FindHostInfo(nsAddrPtr, address, len, hostPtr)
  636.     struct in_addr     *nsAddrPtr;
  637.     struct in_addr    *address;
  638.     int         len;
  639.     HostInfo         *hostPtr;
  640. {
  641.     int      n;
  642.     querybuf buf;
  643.  
  644.     n = res_mkquery(IQUERY, (char *)0, C_IN, T_A,
  645.         (char *)address, len, (char *)0, (char *) &buf, sizeof(buf));
  646.     if (n < 0) {
  647.     if (_res.options & RES_DEBUG) {
  648.         printf("Res_mkquery failed\n");
  649.     }
  650.     return (ERROR);
  651.     }
  652.     return(GetAnswer(nsAddrPtr, T_A, (char *) &buf, n, 1, hostPtr, 1));
  653. }
  654.  
  655. /*
  656. *******************************************************************************
  657. *
  658. *  FreeHostInfoPtr --
  659. *
  660. *    Deallocates all the calloc'd areas for a HostInfo variable.
  661. *
  662. *******************************************************************************
  663. */
  664.  
  665. void
  666. FreeHostInfoPtr(hostPtr)
  667.     register HostInfo *hostPtr;
  668. {
  669.     int i, j;
  670.  
  671.     if (hostPtr->name != NULL) {
  672.     free(hostPtr->name);
  673.     hostPtr->name = NULL;
  674.     }
  675.  
  676.     if (hostPtr->aliases != NULL) {
  677.     i = 0;
  678.     while (hostPtr->aliases[i] != NULL) {
  679.         free(hostPtr->aliases[i]);
  680.         i++;
  681.     }
  682.     free((char *)hostPtr->aliases);
  683.     hostPtr->aliases = NULL;
  684.     }
  685.  
  686.     if (hostPtr->addrList != NULL) {
  687.     i = 0;
  688.     while (hostPtr->addrList[i] != NULL) {
  689.         free(hostPtr->addrList[i]);
  690.         i++;
  691.     }
  692.     free((char *)hostPtr->addrList);
  693.     hostPtr->addrList = NULL;
  694.     }
  695.  
  696.     if (hostPtr->servers != NULL) {
  697.     i = 0;
  698.     while (hostPtr->servers[i] != NULL) {
  699.  
  700.         if (hostPtr->servers[i]->name != NULL) {
  701.         free(hostPtr->servers[i]->name);
  702.         }
  703.  
  704.         if (hostPtr->servers[i]->domains != NULL) {
  705.         j = 0;
  706.         while (hostPtr->servers[i]->domains[j] != NULL) {
  707.             free(hostPtr->servers[i]->domains[j]);
  708.             j++;
  709.         }
  710.         free((char *)hostPtr->servers[i]->domains);
  711.         }
  712.  
  713.         if (hostPtr->servers[i]->addrList != NULL) {
  714.         j = 0;
  715.         while (hostPtr->servers[i]->addrList[j] != NULL) {
  716.             free(hostPtr->servers[i]->addrList[j]);
  717.             j++;
  718.         }
  719.         free((char *)hostPtr->servers[i]->addrList);
  720.         }
  721.         free((char *)hostPtr->servers[i]);
  722.         i++;
  723.     }
  724.     free((char *)hostPtr->servers);
  725.     hostPtr->servers = NULL;
  726.     }
  727. }
  728.  
  729. /*
  730. *******************************************************************************
  731. *
  732. *  GetHostList --
  733. *
  734. *    Performs a completion query when given an incomplete name.
  735. *
  736. *    Still under development.
  737. *
  738. *******************************************************************************
  739. */
  740.  
  741. #if  notdef
  742.  
  743. int
  744. GetHostList(nsAddrPtr, queryType, name, defaultName, hostPtr)
  745.     struct in_addr     *nsAddrPtr;
  746.     int         queryType;
  747.     char         *name, *defaultName;
  748.     HostInfo         *hostPtr;
  749. {
  750.     int     n;
  751.     querybuf    buf;
  752.  
  753.     n = res_mkquery(CQUERYM, name, C_IN, T_A, defaultName, 0, (char *)0,
  754.         (char *) &buf, sizeof(buf));
  755.     if (n < 0) {
  756.         if (_res.options & RES_DEBUG)
  757.             printf("Res_mkquery failed\n");
  758.         return (ERROR);
  759.     }
  760.     return(GetAnswer(nsAddrPtr, queryType, (char *)&buf, n, 0, hostPtr, 1));
  761. }
  762. #endif  notdef
  763.